home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / ccdl151s.zip / SOURCE / INASM386.C < prev    next >
C/C++ Source or Header  |  1997-06-13  |  36KB  |  1,530 lines

  1. /*
  2.  * 68K/386 32-bit C compiler.
  3.  *
  4.  * copyright (c) 1997, David Lindauer
  5.  * 
  6.  * This compiler is intended for educational use.  It may not be used
  7.  * for profit without the express written consent of the author.
  8.  *
  9.  * It may be freely redistributed, as long as this notice remains intact
  10.  * and either the original sources or derived sources 
  11.  * are distributed along with any executables derived from the originals.
  12.  *
  13.  * The author is not responsible for any damages that may arise from use
  14.  * of this software, either idirect or consequential.
  15.  *
  16.  * v1.35 March 1997
  17.  * David Lindauer, gclind01@starbase.spd.louisville.edu
  18.  *
  19.  * Credits to Mathew Brandt for original K&R C compiler
  20.  *
  21.  */
  22. /*
  23.  * inline assembler (386)
  24.  */
  25. #include        <stdio.h> 
  26. #include        "expr.h" 
  27. #include        "c.h" 
  28. #include        "errors.h"
  29. #include                "gen386.h"
  30.  
  31. extern long framedepth, stackdepth, lc_maxauto;
  32.  
  33. extern int asmline;
  34. extern int lastch;
  35. extern int prm_linkreg;
  36. extern enum e_sym lastst;
  37. extern long ival;
  38. extern short *lptr ;
  39. extern TABLE lsyms;
  40. extern int nextlabel;
  41. extern char lastid[];
  42.  
  43. ASMNAME *keyimage;
  44. ASMREG *regimage;
  45. static SYM *lastsym;
  46. static enum e_op op;
  47.  
  48. ASMREG reglst[] = {
  49.     { "cs",am_seg,1,2 },
  50.     { "ds",am_seg,2,2 },
  51.     { "es",am_seg,3,2 },
  52.     { "fs",am_seg,4,2 },
  53.     { "gs",am_seg,5,2 },
  54.     { "ss",am_seg,6,2 },
  55.     { "al",am_dreg,0,1 },
  56.     { "cl",am_dreg,1,1 },
  57.     { "dl",am_dreg,2,1 },
  58.     { "bl",am_dreg,3,1 },
  59.     { "ah",am_dreg,4,1 },
  60.     { "ch",am_dreg,5,1 },
  61.     { "dh",am_dreg,6,1 },
  62.     { "bh",am_dreg,7,1 },
  63.     { "ax",am_dreg,0,2 },
  64.     { "cx",am_dreg,1,2 },
  65.     { "dx",am_dreg,2,2 },
  66.     { "bx",am_dreg,3,2 },
  67.     { "sp",am_dreg,4,2 },
  68.     { "bp",am_dreg,5,2 },
  69.     { "si",am_dreg,6,2 },
  70.     { "di",am_dreg,7,2 },
  71.     { "eax",am_dreg,0,4 },
  72.     { "ecx",am_dreg,1,4 },
  73.     { "edx",am_dreg,2,4 },
  74.     { "ebx",am_dreg,3,4 },
  75.     { "esp",am_dreg,4,4 },
  76.     { "ebp",am_dreg,5,4 },
  77.     { "esi",am_dreg,6,4 },
  78.     { "edi",am_dreg,7,4 },
  79.     { "st",am_freg,0,10 },
  80.     { "cr0",am_screg,0,4 },
  81.     { "cr1",am_screg,2,4 },
  82.     { "cr2",am_screg,3,4 },
  83.     { "cr3",am_screg,4,4 },
  84.     { "cr4",am_screg,5,4 },
  85.     { "cr5",am_screg,6,4 },
  86.     { "cr6",am_screg,7,4 },
  87.     { "cr7",am_screg,8,4 },
  88.     { "dr0",am_sdreg,0,4 },
  89.     { "dr1",am_sdreg,2,4 },
  90.     { "dr2",am_sdreg,3,4 },
  91.     { "dr3",am_sdreg,4,4 },
  92.     { "dr4",am_sdreg,5,4 },
  93.     { "dr5",am_sdreg,6,4 },
  94.     { "dr6",am_sdreg,7,4 },
  95.     { "dr7",am_sdreg,8,4 },
  96.     { "tr0",am_streg,0,4 },
  97.     { "tr1",am_streg,2,4 },
  98.     { "tr2",am_streg,3,4 },
  99.     { "tr3",am_streg,4,4 },
  100.     { "tr4",am_streg,5,4 },
  101.     { "tr5",am_streg,6,4 },
  102.     { "tr6",am_streg,7,4 },
  103.     { "tr7",am_streg,8,4 },
  104.     { "st",am_freg,0,4 },
  105.     { "byte", am_ext,akw_byte,0 },
  106.     { "word", am_ext,akw_word,0 },
  107.     { "dword", am_ext,akw_dword,0 },
  108.     { "fword", am_ext,akw_fword,0 },
  109.     { "qword", am_ext,akw_qword,0 },
  110.     { "tbyte", am_ext,akw_tbyte,0 },
  111.     { "ptr", am_ext, akw_ptr,0 },
  112.     { "offset", am_ext,akw_offset,0 },
  113.     { 0 , 0 , 0 },
  114. };
  115.  
  116. static int floating;
  117.  
  118. void inasmini(void)
  119. {
  120. }
  121. static void asm_err(int errnum)
  122. {
  123.     *lptr = 0;
  124.     lastch = ' ';
  125.     generror(errnum,0,0);
  126.     getsym();
  127. }
  128. static ENODE *asm_ident(void)
  129. {
  130.     ENODE *node = 0;
  131.     char *nm;
  132.     int fn = FALSE;
  133.     if (lastst != id)
  134.         asm_err(ERR_IDEXPECT);
  135.     else {
  136.         SYM             *sp;
  137.                 ENODE *qnode = 0;
  138.                 nm = litlate(lastid);
  139.                 getsym();
  140. /* No such identifier */
  141. /* label, put it in the symbol table */
  142.         if( (sp = gsearch(nm)) == 0 ) { 
  143.                                 sp = xalloc(sizeof(SYM)); 
  144.                                 sp->name = nm; 
  145.                                 sp->storage_class = sc_ulabel; 
  146.                                                 sp->tp = xalloc(sizeof(TYP));
  147.                                                 sp->tp->type = bt_unsigned;
  148.                                                 sp->tp->uflags = UF_USED;
  149.                                 sp->value.i = nextlabel++; 
  150.                                 insert(sp,&lsyms); 
  151.                         node = xalloc(sizeof(ENODE));
  152.                         node->nodetype = en_labcon;
  153.                         node->v.i = sp->value.i;
  154.                 }
  155.         else    {
  156. /* If we get here the symbol was already in the table
  157.  */
  158. foundsp:
  159.                                 sp->tp->uflags |= UF_USED;
  160.                 switch( sp->storage_class ) {
  161.                         case sc_static:
  162.                         case sc_global:
  163.                         case sc_external:
  164.                         case sc_externalfunc:
  165.                                                 case sc_abs:
  166.                                                                 sp->extflag = TRUE;
  167.                                                                 if (sp->tp->type == bt_ptrfunc || sp->tp->type == bt_func || sp->tp->type == bt_ifunc) {
  168. /* make a function node */
  169.                                                                     if (sp->tp->type == bt_ptrfunc)
  170.                                         node = makenode(en_nacon,sp,0);
  171.                                                                     else
  172.                                         node = makenode(en_napccon,sp,0);
  173. isfunc:
  174.                                                                     if (sp->tp->type != bt_ptrfunc && sp->tp->type != bt_func && sp->tp->type != bt_ifunc)
  175.                                                                         generror(ERR_MISMATCH,0,0);
  176.                                                                 }
  177.                                                                 else
  178. /* otherwise make a node for a regular variable */
  179.                                                                     if (sp->absflag)
  180.                                         node = makenode(en_absacon,sp,0);
  181.                                                                     else
  182.                                                                         if (sp->tp->type == bt_func || sp->tp->type == bt_ifunc) {
  183.                                                                             fn = TRUE;
  184.                                             node = makenode(en_napccon,sp,0);
  185.                                                                         }
  186.                                                                         else
  187.                                                                             if (sp->staticlabel)
  188.                                                                                 node = makenode(en_nalabcon,(char *)sp->value.i,0);
  189.                                                                             else
  190.                                                 node = makenode(en_nacon,sp,0);
  191.                                 break;
  192.                         case sc_const:
  193. /* constants and enums */
  194.                                 node = makenode(en_icon,(char *)sp->value.i,0);
  195.                                                                 break;
  196.                                                 case sc_label:
  197.                                                 case sc_ulabel:
  198.                                             node = xalloc(sizeof(ENODE));
  199.                                             node->nodetype = en_labcon;
  200.                                             node->v.i = sp->value.i;
  201.                                                     break;
  202.                         default:        /* auto and any errors */
  203.                                 if( sp->storage_class != sc_auto && sp->storage_class != sc_autoreg) {
  204.                                         gensymerror(ERR_ILLCLASS2,sp->name);
  205.                                                                 }
  206.                                                                 else {
  207. /* auto variables */
  208.                                                                      if (sp->storage_class == sc_auto)
  209.                                         node = makenode(en_autocon,sp,0);
  210.                                                                     else if (sp->storage_class == sc_autoreg)
  211.                                         node = makenode(en_autoreg,sp,0);
  212.                                                                     if (fn)
  213.                                                                         goto isfunc;
  214.                                                                 }
  215.                                 break;
  216.                         }
  217.  
  218.                                 (node)->cflags = 0;
  219.                 }
  220.                 lastsym = sp;
  221.     }
  222.     return node;
  223. }
  224. static ENODE * asm_label(void)
  225. {
  226.     char *nm = litlate(lastid);
  227.     ENODE *node;
  228.     SYM *sp;
  229.                 getsym();
  230. /* No such identifier */
  231. /* label, put it in the symbol table */
  232.         if( (sp = search(lastid,&lsyms)) == 0 ) { 
  233.                                 sp = xalloc(sizeof(SYM)); 
  234.                                 sp->name = litlate(lastid); 
  235.                                 sp->storage_class = sc_label; 
  236.                                                 sp->tp = xalloc(sizeof(TYP));
  237.                                                 sp->tp->type = bt_unsigned;
  238.                                                 sp->tp->uflags = 0;
  239.                                 sp->value.i = nextlabel++; 
  240.                                 insert(sp,&lsyms); 
  241.                 }
  242.         else    {
  243.                     if (sp->storage_class == sc_label) {
  244.                         asm_err(ERR_DUPLABEL);
  245.                         return 0;
  246.                     }
  247.                     if (sp->storage_class != sc_ulabel) {
  248.                         asm_err(ERR_ALABEXPECT);
  249.                         return 0;
  250.                     }
  251.                     sp->storage_class = sc_label;
  252.                 }
  253.         if (lastst != colon) {
  254.             asm_err(ERR_ALABEXPECT);
  255.             return 0;
  256.         }
  257.         getsym();
  258.     node = xalloc(sizeof(ENODE));
  259.     node->nodetype = en_labcon;
  260.     node->v.i = sp->value.i;
  261.         return node;
  262. }
  263. static int asm_getsize(void)
  264. {
  265.     int sz=0;
  266.     switch (regimage->regnum) {
  267.             case akw_byte: sz = 1; break;
  268.             case akw_word: sz = 2; break;
  269.             case akw_dword: sz = floating ? 6 : 4; break;
  270.             case akw_fword: sz = 6; break;
  271.             case akw_qword: sz = 8; break;
  272.             case akw_tbyte: sz = 10; break;
  273.             case akw_offset: sz = 4; break;
  274.     };
  275.     getsym();
  276.     if (lastst == kw_asmreg) {
  277.         regimage = keyimage;
  278.         if (regimage->regtype == am_ext) {
  279.             if (regimage->regnum != akw_ptr) {
  280.                 asm_err(ERR_AILLADDRESS);
  281.                 return 0;
  282.             }
  283.             getsym();
  284.         }
  285.     }
  286.     if (lastst != kw_asmreg && lastst != openbr && lastst != id) {
  287.         asm_err(ERR_AMODEEXPECT);
  288.         return 0;
  289.     }
  290.     regimage=keyimage;
  291.     return sz;
  292. }
  293. static int getscale (int *scale)
  294. {
  295.     if (lastst == star) {
  296.         getsym();
  297.         if (lastst == iconst && !*scale) 
  298.             if (ival== 1 || ival==2 || ival==4 || ival==8) {
  299.                 if (ival < 3)    
  300.                     ival--;
  301.                 else
  302.                     ival = ival/4+1;
  303.                 *scale =ival;
  304.                 getsym();
  305.                 return 1;
  306.             }
  307.         asm_err(ERR_ASCALE);
  308.         *scale = -1;
  309.         return 1;
  310.     }
  311.     return 0;
  312. }
  313. int asm_enterauto(ENODE *node, int *reg1, int *reg2)
  314. {
  315.     if (node && (node->nodetype == en_autocon || node->nodetype == en_autoreg)) {
  316.                                 int *vreg;
  317.                                 if (*reg1 >=0 && *reg2 >=0) {
  318.                                     asm_err(ERR_AINVINDXMODE);
  319.                                     return 0;
  320.                                 }
  321.                                 if (reg1 < 0)
  322.                                     vreg = reg1;
  323.                                 else
  324.                                     vreg = reg2    ;
  325.                                 *vreg = ESP;
  326.                                 if (prm_linkreg) {
  327.                           *vreg = EBP;
  328.                                 }
  329.                                 return 1;
  330.     }
  331.     return 2;
  332. }
  333. static AMODE *asm_mem(void)
  334. {
  335.     int reg1=-1, reg2=-1, scale=0, temp,sz=0;
  336.     ENODE *node=0;
  337.     AMODE *rv;
  338.     int gotident = FALSE,autonode = FALSE;
  339.     while (TRUE) {
  340.         int rg;
  341.         getsym();
  342.         regimage = keyimage;
  343.         rg = regimage->regnum;
  344.         switch(lastst) {
  345.             case kw_asmreg:
  346.                 regimage = keyimage;
  347.                 if (regimage->regtype != am_dreg || regimage->size != 4) {
  348.                     asm_err(ERR_AINVINDXMODE);
  349.                     return 0;
  350.                 }    
  351.                 if (reg1 >= 0) {
  352.                     if (reg2 >=0) {
  353.                         asm_err(ERR_AINVINDXMODE);
  354.                         return 0;
  355.                     }
  356.                     reg2 = rg;
  357.                     getsym();
  358.                     getscale(&scale);
  359.                     if (scale == -1)
  360.                         return 0;
  361.                 }
  362.                 else {
  363.                     getsym();
  364.                     if (getscale(&scale)) {
  365.                         if (scale == -1)
  366.                             return 0;
  367.                         if (reg2 >= 0) {
  368.                             reg1 = reg2;
  369.                         }
  370.                         reg2 = rg;
  371.                     }
  372.                     else {
  373.                         reg1 = rg;
  374.                     }
  375.                 }
  376.                 break;
  377.             case iconst:
  378.                 if (node)
  379.                     node = makenode(en_add,node,makenode(en_icon,(char *)intexpr(0),0));
  380.                 else
  381.                     node = makenode(en_icon,(char *)intexpr(0),0);
  382.                 break;
  383.             case id:
  384.                 if (gotident) {
  385.                     asm_err(ERR_AINVINDXMODE);
  386.                     return 0;
  387.                 }
  388.                 node = asm_ident();
  389.                 gotident = TRUE;
  390.                 sz = lastsym->tp->size;
  391.                 switch(asm_enterauto(node,®1,®2)) {
  392.                     case 0:
  393.                         return 0;
  394.                     case 1:
  395.                         autonode = TRUE;
  396.                         break;
  397.                     case 2:
  398.                         autonode = FALSE;
  399.                         break;
  400.                 }
  401.                 break;
  402.             default:
  403.                 asm_err(ERR_AILLADDRESS);
  404.                 return 0;
  405.         }
  406.         if (lastst == closebr) {
  407.             getsym();
  408.             break;
  409.         }
  410.         if (lastst != plus) {
  411.             asm_err(ERR_AINVINDXMODE);
  412.             return 0;
  413.         }
  414.     }
  415.     if ((reg2 == 4 || reg2 == 5) && scale > 1) {
  416.         asm_err(ERR_AINVINDXMODE);
  417.         return 0;
  418.     }
  419.     rv = xalloc(sizeof(AMODE));
  420.     if (node) {
  421.         rv->offset = node;
  422.     }
  423.     if (reg1 >=0) {
  424.         rv->preg = reg1;
  425.         if (reg2 >=0) {
  426.             rv->sreg = reg2;
  427.             rv->scale = scale;
  428.             rv->mode = am_indispscale;
  429.         }
  430.         else {
  431.             rv->mode = am_indisp;
  432.         }
  433.     }
  434.     else
  435.         if (reg2 >=0) {
  436.             rv->preg = -1;
  437.             rv->sreg = reg2;
  438.             rv->scale = scale;
  439.             rv->mode = am_indispscale;
  440.         }
  441.         else
  442.             rv->mode = am_direct;
  443.     return rv;
  444. }
  445. static AMODE *asm_amode(int nosegreg)
  446. {
  447.     AMODE *rv=xalloc(sizeof(AMODE));
  448.     int sz = 0,seg=0;
  449.     lastsym = 0;
  450.     switch (lastst) {
  451.       case iconst:
  452.         case iuconst:
  453.         case lconst:
  454.         case luconst:
  455.         case cconst:
  456.                 case kw_asmreg:
  457.                 case openbr:
  458.                 case id:
  459.                     break;
  460.                 default:
  461.                     asm_err(ERR_AMODEEXPECT);
  462.                     return 0;
  463.     }
  464.     if (lastst== kw_asmreg) {
  465.         regimage = keyimage;
  466.         if (regimage->regtype == am_ext) {
  467.             sz = asm_getsize();
  468.             regimage = keyimage;
  469.         }
  470.     }
  471. loop:
  472.         switch (lastst) {
  473.             case kw_asmreg:
  474.                 if (regimage->regtype == am_ext) {
  475.                     asm_err(ERR_ATOOMANYSPECS);
  476.                     return 0;
  477.                 }
  478.                 if (regimage->regtype == am_freg) {
  479.                         getsym();
  480.                         if (lastst == openpa) {
  481.                             getsym();
  482.                             if (lastst != iconst || ival < 0 || ival > 7) {
  483.                                 asm_err(ERR_ANEEDFP);
  484.                                 return 0;
  485.                             }
  486.                             getsym();
  487.                             needpunc(closepa,0);
  488.                         }
  489.                         else ival = 0;
  490.                         rv->preg = ival;
  491.                         rv->mode = am_freg;
  492.                         sz = 10;
  493.                     }
  494.                     else if (regimage->regtype == am_seg) {
  495.                         if (rv->seg) {
  496.                             asm_err(ERR_ATOOMANYSEGS);
  497.                             return 0;
  498.                         }
  499.                         rv->seg = seg = regimage->regnum;
  500.                         getsym();
  501.                         if (lastst == colon) {
  502.                             getsym();
  503.                             goto loop;
  504.                         }
  505.                         rv->mode = am_seg;
  506.                         sz = regimage->size;
  507.                     }
  508.                     else {
  509.                         rv->preg = regimage->regnum;
  510.                         rv->mode = regimage->regtype;
  511.                         sz = regimage->size;
  512.                         getsym();
  513.                     }
  514.                 break;
  515.             case openbr:
  516.                 rv = asm_mem();
  517.                 break;
  518.             case id:
  519.                 rv->mode = am_immed;
  520.                 rv->offset = asm_ident();
  521.                 rv->length = 4;
  522.                 if (rv->offset->nodetype == en_autocon || rv->offset->nodetype == en_autoreg) {
  523.                     asm_err(ERR_AUSELEA);
  524.                     return 0;
  525.                 }
  526.                 break;
  527.       case iconst:
  528.         case iuconst:
  529.         case lconst:
  530.         case luconst:
  531.         case cconst:
  532.                 rv = make_immed(ival);
  533.                                 getsym();
  534.                       break;
  535.             default:
  536.                 asm_err(ERR_AILLADDRESS);
  537.                 return 0;                
  538.     }
  539.     if (rv) {
  540.         if (rv->seg) 
  541.             if (nosegreg || rv->mode != am_dreg)
  542.                 if (rv->mode != am_direct && rv->mode != am_indisp && rv->mode != am_indispscale && rv->mode != am_seg) {
  543.                     asm_err(ERR_ATOOMANYSEGS);
  544.                     return 0;
  545.                 }
  546.         if (!rv->length)
  547.             if (sz)    
  548.                 rv->length = sz;
  549.             else if (lastsym)
  550.                 rv->length = lastsym->tp->size;
  551.         if (rv->length < 0)
  552.             rv->length = - rv->length;
  553.         rv->seg = seg;
  554.     }
  555.     return rv;
  556. }
  557. static AMODE *asm_immed(void)
  558. {
  559.     AMODE *rv;
  560.     switch(lastst) {
  561.       case iconst:
  562.         case iuconst:
  563.         case lconst:
  564.         case luconst:
  565.         case cconst:
  566.                 rv = make_immed(ival);
  567.                                 rv->length = 4;
  568.                                 getsym();
  569.                                 return rv;
  570.     }
  571.     return 0;
  572. }
  573. int isrm(AMODE* ap, int dreg_allowed)
  574. {
  575.     switch (ap->mode) {
  576.         case am_dreg:
  577.             return dreg_allowed;
  578.         case am_indisp:
  579.         case am_direct:
  580.         case am_indispscale:
  581.             return 1;
  582.         default:
  583.             return 0;
  584.     }
  585. }
  586. AMODE *getimmed(void)
  587. {
  588.     AMODE *rv;
  589.     switch(lastst) {
  590.       case iconst:
  591.         case iuconst:
  592.         case lconst:
  593.         case luconst:
  594.         case cconst:
  595.                 rv = make_immed(ival);
  596.                                 getsym();
  597.                                 return rv;
  598.             default:
  599.                 return 0;
  600.     }
  601. }
  602. enum e_op asm_op(void)
  603. {
  604.     int op;
  605.     if (lastst != kw_asminst) {
  606.         asm_err(ERR_AINVOP);
  607.         return -1;
  608.     }
  609.     op = keyimage->atype;
  610.     getsym();
  611.     floating = op >= op_f2xm1;
  612.     return op;
  613. }
  614. static OCODE *make_ocode(AMODE *ap1, AMODE *ap2, AMODE *ap3)
  615. {
  616.     OCODE *o = xalloc(sizeof(OCODE));
  617.     o->oper1 = ap1;
  618.     o->oper2 = ap2;
  619.     o->oper3 = ap3;
  620.     return o;
  621. }
  622. static OCODE *ope_math (void)
  623. {
  624.     AMODE *ap1,*ap2;
  625.     ap1 = asm_amode(TRUE);
  626.     if (!ap1)
  627.         return 0;
  628.     if (!isrm(ap1,TRUE))
  629.         return (OCODE *)-1;
  630.     needpunc(comma,0);
  631.     ap2 = asm_amode(TRUE);
  632.     if (!ap2)
  633.         return 0;
  634.     if (ap1->mode != am_dreg) {
  635.         if (ap2->mode != am_immed && ap2->mode != am_dreg)
  636.             return (OCODE *)-1;
  637.     }
  638.     else
  639.         if (!isrm(ap2,TRUE) && ap2->mode != am_immed)
  640.             return (OCODE *)-1;
  641.     if (ap2->mode != am_immed)
  642.         if (ap1->length && ap2->length && ap1->length != ap2->length)
  643.             return (OCODE *) -2;
  644.  
  645.     return make_ocode(ap1,ap2,0);
  646. }
  647. static OCODE *ope_arpl (void)
  648. {
  649.     AMODE *ap1,*ap2;
  650.     ap1 = asm_amode(TRUE);
  651.     if (!ap1)
  652.         return 0;
  653.     if (!isrm(ap1,TRUE))
  654.         return (OCODE *)-1;
  655.     needpunc(comma,0);
  656.     ap2 = asm_amode(TRUE);
  657.     if (!ap2)
  658.         return 0;
  659.      if (ap2->mode != am_dreg)
  660.         return (OCODE *)-1;
  661.     if (!ap1->length || !ap2->length || ap1->length != ap2->length || ap1->length != 2)
  662.         return (OCODE *) -2;
  663.  
  664.     return make_ocode(ap1,ap2,0);
  665. }
  666. static OCODE *ope_bound (void)
  667. {
  668.     AMODE *ap1,*ap2;
  669.     ap1 = asm_amode(TRUE);
  670.     if (!ap1)
  671.         return 0;
  672.   if (ap1->mode != am_dreg)
  673.         return (OCODE *)-1;
  674.     needpunc(comma,0);
  675.     ap2 = asm_amode(TRUE);
  676.     if (!ap2)
  677.         return 0;
  678.     if (!isrm(ap2,FALSE))
  679.         return (OCODE *)-1;
  680.     switch(ap1->length) {
  681.         case 1:
  682.             return (OCODE *)-1;
  683.         case 2:
  684.             if (ap2->length != 4) {
  685.                 return (OCODE *) -2;
  686.             }
  687.             break;
  688.         case 4:
  689.             if (ap2->length != 8) {
  690.                 return (OCODE *) -2;
  691.             }
  692.             break;
  693.     }
  694.     return make_ocode(ap1,ap2,0);
  695. }
  696. static OCODE *ope_bitscan (void)
  697. {
  698.     AMODE *ap1,*ap2;
  699.     ap1 = asm_amode(TRUE);
  700.     if (!ap1)
  701.         return 0;
  702.     if (ap1->mode != am_dreg)
  703.         return (OCODE *)-1;
  704.     needpunc(comma,0);
  705.     ap2 = asm_amode(TRUE);
  706.     if (!ap2)
  707.         return 0;
  708.     if (!isrm(ap2,TRUE))
  709.         return (OCODE *)-1;
  710.     if (ap1->length == 1 || ap2->length != ap1->length)
  711.         return (OCODE *) -2;
  712.     return make_ocode(ap1,ap2,0);
  713.     
  714. }
  715. static OCODE *ope_bit (void)
  716. {
  717.     AMODE *ap1,*ap2;
  718.     ap1 = asm_amode(TRUE);
  719.     if (!ap1)
  720.         return 0;
  721.     if (!isrm(ap1,TRUE))
  722.         return (OCODE *)-1;
  723.     needpunc(comma,0);
  724.     ap2 = asm_amode(TRUE);
  725.     if (!ap2) 
  726.         return 0;
  727.     if (ap2->mode != am_immed && ap2->mode != am_dreg)
  728.         return (OCODE *)-1;
  729.     if (ap1->length == 1 || ap2->mode == am_dreg && ap2->length == 1)
  730.         return (OCODE *) -2;
  731.     return make_ocode(ap1,ap2,0);
  732. }
  733. static OCODE *ope_call (void)
  734. {  
  735.     AMODE *ap1=asm_amode(TRUE);
  736.     if (!ap1)
  737.         return 0;
  738.     if (ap1->mode == am_immed) {
  739.         if (ap1->offset->nodetype != en_nalabcon && ap1->offset->nodetype != en_labcon 
  740.                 && ap1->offset->nodetype != en_napccon || ap1->seg)
  741.             return (OCODE *)-1;
  742.     }
  743.     else {
  744.         if (!isrm(ap1,TRUE))
  745.             return (OCODE *)-1;
  746.         if ((ap1->length != 4) && (ap1->length != 6))
  747.             return (OCODE *) -2;
  748.     }
  749.     return make_ocode(ap1,0,0);
  750. }
  751. static OCODE *ope_incdec (void)
  752. {
  753.     AMODE *ap1=asm_amode(TRUE);
  754.     if (!ap1)
  755.         return 0;
  756.     if (!isrm(ap1,TRUE))
  757.         return (OCODE *)-1;
  758.     if (ap1->length >4) {
  759.         return (OCODE *) -2;
  760.     }
  761.     return make_ocode(ap1,0,0);
  762. }
  763. static OCODE *ope_rm (void)
  764. {
  765.     return(ope_incdec());
  766. }
  767. static OCODE *ope_enter (void)
  768. {
  769.     AMODE *ap1, *ap2;
  770.     ap1 = asm_immed();
  771.     if (!ap1)
  772.         return 0;
  773.     needpunc(comma,0);
  774.     ap2 = asm_immed();
  775.     if (!ap2)
  776.         return 0;
  777.     return make_ocode(ap1,ap2,0);
  778. }
  779. static OCODE *ope_imul (void)
  780. {
  781.     AMODE *ap1 = asm_amode(TRUE),*ap2=0,*ap3=0;
  782.     if (!ap1)
  783.         return 0;
  784.     if (!isrm(ap1,TRUE))
  785.         return (OCODE *)-1;
  786.     if (lastst == comma) {
  787.         getsym();
  788.         ap2 = asm_amode(TRUE);
  789.         if (lastst == comma) {
  790.             getsym();
  791.             ap3 = asm_amode(TRUE);
  792.         }
  793.     }
  794.     if (ap2) {
  795.         if (ap1->mode != am_dreg || ap1->length == 1)
  796.             return (OCODE *)-1;
  797.         if (!isrm(ap2,TRUE) && ap2->mode != am_immed)
  798.             return (OCODE *)-1;
  799.         if (ap3)
  800.             if (ap2->mode == am_immed || ap3->mode != am_immed)
  801.                 return (OCODE *)-1;
  802.     }
  803.     return make_ocode(ap1,ap2,ap3);
  804. }
  805. static OCODE *ope_in (void)
  806. {
  807.     AMODE *ap1 = asm_amode(TRUE),*ap2;
  808.     if (!ap1)
  809.         return 0;
  810.     if (ap1-> mode != am_dreg || ap1->preg != 0)
  811.         return (OCODE *)-1;
  812.     needpunc(comma,0);
  813.     ap2 = asm_amode(TRUE);
  814.     if (!ap2)
  815.         return 0;
  816.     if (ap2->mode != am_immed &&( ap2->mode != am_dreg || ap2->preg != 2 || ap2->length !=2))
  817.         return (OCODE *)-1;
  818.     return make_ocode(ap1,ap2,0);
  819. }
  820. static OCODE *ope_imm8 (void)
  821. {
  822.     AMODE *ap1 = asm_immed();
  823.     if (!ap1)
  824.         return 0;
  825.     return make_ocode(ap1,0,0);
  826. }
  827. static OCODE *ope_relbra (void)
  828. {
  829.     AMODE *ap1=asm_amode(TRUE);
  830.     if (!ap1)
  831.         return 0;
  832.     if (ap1->mode != am_immed)
  833.         return (OCODE *)-1;
  834.     if (ap1->offset->nodetype != en_nalabcon && ap1->offset->nodetype != en_labcon)
  835.       return (OCODE *)-1;
  836.     return make_ocode(ap1,0,0);
  837. }
  838. static OCODE *ope_relbr8 (void)
  839. {
  840.     return ope_relbra();
  841. }
  842. static OCODE *ope_jmp (void)
  843. {
  844.     return ope_call();
  845. }
  846. static OCODE *ope_regrm (void)
  847. {
  848.     AMODE *ap1,*ap2;
  849.     ap1 = asm_amode(TRUE);
  850.     if (!ap1) 
  851.         return 0;
  852.     if (ap1->mode != am_dreg)
  853.         return (OCODE *)-1;
  854.     needpunc(comma,0);
  855.     ap2 = asm_amode(TRUE);
  856.     if (!ap2) 
  857.         return 0;
  858.     if (!isrm(ap2,TRUE))
  859.         return (OCODE *)-1;
  860.     if (op == op_lea && ap2->mode == am_dreg)
  861.         return (OCODE *)-1;
  862.     if (ap2->length && ap1->length != ap2->length || ap1->length == 1)
  863.         return (OCODE *)-2;
  864.     return make_ocode(ap1,ap2,0);
  865. }
  866. static OCODE *ope_loadseg (void)
  867. {
  868.     AMODE *ap1,*ap2;
  869.     ap1 = asm_amode(TRUE);
  870.     if (!ap1)
  871.         return 0;
  872.     if (ap1->mode != am_dreg)
  873.         return (OCODE *)-1;
  874.     needpunc(comma,0);
  875.     ap2 = asm_amode(TRUE);
  876.     if (!ap2)
  877.         return 0;
  878.     if (!isrm(ap2,TRUE))
  879.         return (OCODE *)-1;
  880.     if (ap1->length != 4 || ap2->length != 6)
  881.         return (OCODE *)-1;
  882.     return make_ocode(ap1,ap2,0);
  883. }
  884. static OCODE *ope_lgdt (void)
  885. {
  886.     AMODE *ap1,*ap2;
  887.     ap1 = asm_amode(TRUE);
  888.     if (!ap1)
  889.         return 0;
  890.      if (!isrm(ap1,FALSE) || ap1->length != 6)
  891.         return (OCODE *)-1;
  892.     return make_ocode(ap1,0,0);
  893. }
  894. static OCODE *ope_lidt (void)
  895. {
  896.     return ope_lgdt();
  897. }
  898. static OCODE *ope_rm16 (void)
  899. {
  900.     AMODE *ap1,*ap2;
  901.     ap1 = asm_amode(TRUE);
  902.     if (!ap1)
  903.         return 0;
  904.   if (!isrm(ap1,TRUE) || ap1->length != 2)
  905.         return (OCODE *)-1;
  906.     return make_ocode(ap1,0,0);
  907. }
  908. static OCODE *ope_mov (void)
  909. {
  910.     AMODE *ap1 = asm_amode(TRUE),*ap2;
  911.     if (!ap1)
  912.         return 0;
  913.     if (!isrm(ap1,TRUE) && ap1->mode != am_seg && ap1->mode != am_screg && ap1->mode != am_sdreg && ap1->mode != am_streg)
  914.         return (OCODE *)-1;
  915.     needpunc(comma,0);
  916.     ap2 = asm_amode(TRUE);
  917.     if (!ap2)
  918.         return 0;
  919.     if (ap1->mode == am_dreg) {
  920.         if (!isrm(ap2,TRUE) && ap2->mode != am_immed && (ap2->length != 4 || (ap2->mode != am_screg && ap2->mode != am_sdreg && ap2->mode != am_streg)))
  921.             return (OCODE *)-1;
  922.     }
  923.     else if (isrm(ap1,TRUE)) {
  924.         if (ap2->mode != am_dreg && ap2->mode != am_immed && ap2->mode != am_seg)
  925.             return (OCODE *)-1;
  926.     }
  927.     else if (ap1->mode == am_seg) {
  928.         if (!isrm(ap2,TRUE))
  929.             return (OCODE *)-1;
  930.     }
  931.     else if (ap2->length != 4 || ap2->mode != am_dreg)
  932.         return (OCODE *)-1;
  933.     if (ap1->length && ap2->length && ap1->length != ap2->length)
  934.         return (OCODE *) -2;
  935.     return make_ocode(ap1,ap2,0);
  936. }
  937. static OCODE *ope_movsx (void)
  938. {
  939.     AMODE *ap1,*ap2;
  940.     ap1 = asm_amode(TRUE);
  941.     if (!ap1)
  942.         return 0;
  943.      if (ap1->mode != am_dreg)
  944.         return (OCODE *)-1;
  945.     needpunc(comma,0);
  946.     ap2 = asm_amode(TRUE);
  947.     if (!ap2)
  948.         return 0;
  949.     if (!isrm(ap2,TRUE))
  950.         return (OCODE *)-1;
  951.     if (!ap2->length || ap1->length <= ap2->length) {
  952.         asm_err(ERR_AINVSIZE);
  953.     }
  954.     return make_ocode(ap1,ap2,0);
  955. }
  956. static OCODE *ope_out (void)
  957. {
  958.     AMODE *ap1 = asm_amode(TRUE),*ap2;
  959.     if (!ap1)
  960.         return 0;
  961.     if (ap1->mode != am_immed &&( ap1->mode != am_dreg || ap1->preg != 2 || ap1->length !=2))
  962.         return (OCODE *)-1;
  963.     needpunc(comma,0);
  964.     ap2 = asm_amode(TRUE);
  965.     if (!ap2)
  966.         return 0;
  967.     if (ap2-> mode != am_dreg || ap2->preg != 0)
  968.         return (OCODE *)-1;
  969.     return make_ocode(ap1,ap2,0);
  970. }
  971. static OCODE *ope_pushpop (void)
  972. {
  973.     AMODE *ap1;
  974.     ap1 = asm_amode(TRUE);
  975.     if (!ap1)
  976.         return 0;
  977.     if (!isrm(ap1,TRUE) && ap1->mode != am_seg && ap1->mode != am_immed || (ap1->mode == am_immed && op == op_pop))
  978.         return (OCODE *)-1;
  979.     if (ap1->mode != am_immed && ap1->length !=2 && ap1->length != 4 ) {
  980.         return (OCODE *) -2;
  981.     }
  982.     if (op == op_pop && ap1->mode == am_seg && ap1->seg == 1)
  983.         return (OCODE *) -1;
  984.     return make_ocode (ap1,0,0);
  985. }
  986. static OCODE *ope_shift (void)
  987. {
  988.     AMODE *ap1,*ap2;
  989.     ap1 = asm_amode(2);
  990.     if (!ap1)
  991.         return 0;
  992.     if (!isrm(ap1,TRUE))
  993.         return (OCODE *)-1;
  994.     needpunc(comma,0);
  995.     ap2 = asm_amode(TRUE);
  996.     if (!ap2)
  997.         return 0;
  998.     if (ap2->mode != am_immed && ap2->mode != am_dreg)
  999.         return (OCODE *)-1;
  1000.     if (ap2->mode == am_dreg)
  1001.         if (ap2->preg != 1 || ap2->length != 1)
  1002.             return (OCODE *)-1;
  1003.     return make_ocode(ap1,ap2,0);
  1004. }
  1005. static OCODE *ope_ret (void)
  1006. {
  1007.     AMODE *ap1 ;
  1008.     if (lastst != iconst)
  1009.         return make_ocode(0,0,0);
  1010.     ap1 = asm_amode(TRUE);
  1011.     return make_ocode(ap1,0,0);
  1012. }
  1013. static OCODE *ope_set (void)
  1014. {
  1015.     AMODE *ap1;
  1016.     ap1 = asm_amode(TRUE);
  1017.     if (!ap1)
  1018.         return 0;
  1019.   if (!isrm(ap1,TRUE) || ap1 ->length != 1)
  1020.         return (OCODE *)-1;
  1021.     return make_ocode(ap1,0,0);
  1022. }
  1023. static OCODE *ope_shld (void)
  1024. {
  1025.     AMODE *ap1,*ap2,*ap3;
  1026.     ap1 = asm_amode(TRUE);
  1027.     if (!ap1)
  1028.         return 0;
  1029.     if (!isrm(ap1,TRUE))
  1030.         return (OCODE *)-1;
  1031.     needpunc(comma,0);
  1032.     ap2 = asm_amode(TRUE);
  1033.     if (!ap2)
  1034.         return 0;
  1035.     if (ap2->mode != am_dreg || ap2->length == 1)
  1036.         return (OCODE *)-1;
  1037.     if (ap1->length != ap2->length) {
  1038.         asm_err(ERR_AINVSIZE);
  1039.     }
  1040.     needpunc(comma,0);
  1041.     ap3 = asm_amode(TRUE);
  1042.     if (!ap3)
  1043.         return 0;
  1044.     if (ap3->mode != am_immed && ap3->mode != am_dreg)
  1045.         return (OCODE *)-1;
  1046.     if (ap3->mode == am_dreg)
  1047.         if (ap3->preg != 1 || ap3->length != 1)
  1048.             return (OCODE *)-1;
  1049.     return make_ocode(ap1,ap2,ap3);
  1050. }
  1051. static OCODE *ope_test (void)
  1052. {
  1053.     AMODE *ap1,*ap2;
  1054.     ap1 = asm_amode(TRUE);
  1055.     if (!ap1)
  1056.         return 0;
  1057.     if (!isrm(ap1,TRUE))
  1058.         return (OCODE *)-1;
  1059.     needpunc(comma,0);
  1060.     ap2 = asm_amode(TRUE);
  1061.     if (!ap2)
  1062.         return 0;
  1063.     if (ap2->mode != am_dreg && ap2->mode != am_immed)
  1064.         return (OCODE *)-1;
  1065.     if (ap2->mode == am_dreg && ap1->length != ap2->length) {
  1066.         return (OCODE *) -2;
  1067.     }
  1068.     return make_ocode(ap1,ap2,0);
  1069. }
  1070. static OCODE *ope_xchg (void)
  1071. {
  1072.     AMODE *ap1, *ap2;
  1073.     ap1 = asm_amode(TRUE);
  1074.     if (!ap1)
  1075.         return 0;
  1076.     if (!isrm(ap1,TRUE))
  1077.         return (OCODE *)-1;
  1078.     needpunc(comma,0);
  1079.     ap2 = asm_amode(TRUE);
  1080.     if (!ap2)
  1081.         return 0;
  1082.     if (ap1->mode == am_dreg) {
  1083.         if (!isrm(ap2,TRUE))
  1084.             return (OCODE *)-1;
  1085.     }
  1086.     else
  1087.         if (ap2->mode != am_dreg)
  1088.             return (OCODE *)-1;
  1089.     if (ap1->length != ap2->length)
  1090.         return (OCODE *)-2;
  1091.     return make_ocode(ap1,ap2,0);
  1092. }
  1093. static OCODE *ope_fmath (void)
  1094. {
  1095.     AMODE *ap1, *ap2=0;
  1096.     ap1 = asm_amode(TRUE);
  1097.     if (!ap1)
  1098.         return 0;
  1099.     if (isrm(ap1,FALSE)) {
  1100.         if (ap1->length != 6 && ap1->length != 8)
  1101.             return (OCODE *) -2;
  1102.     }
  1103.     else {
  1104.         if (ap1->mode != am_freg)
  1105.             return (OCODE *)-1;
  1106.         needpunc(comma,0);
  1107.         ap2 = asm_amode(TRUE);
  1108.         if (ap2->mode != am_freg)
  1109.             return (OCODE *)-1;
  1110.         if (ap1->preg && ap2->preg)
  1111.             return (OCODE *)-1;
  1112.     }
  1113.     return make_ocode(ap1,ap2,0);
  1114. }
  1115. static OCODE *ope_fmathp (void)
  1116. {
  1117.     AMODE *ap1, *ap2;
  1118.     if (lastst != kw_asmreg)
  1119.         return make_ocode(0,0,0);
  1120.     ap1 = asm_amode(TRUE);
  1121.     if (!ap1)
  1122.         return 0;
  1123.     if (ap1->mode != am_freg)
  1124.         return (OCODE *)-1;
  1125.     needpunc(comma,0);
  1126.     ap2 = asm_amode(TRUE);
  1127.     if (!ap2)
  1128.         return 0;
  1129.     if (ap2->mode != am_freg)
  1130.       return (OCODE *)-1;
  1131.     if (ap1->preg && ap2->preg)
  1132.       return (OCODE *)-1;
  1133.     return make_ocode(ap1,ap2,0);
  1134. }
  1135. static OCODE *ope_fmathi (void)
  1136. {
  1137.     AMODE *ap1;
  1138.     ap1 = asm_amode(TRUE);
  1139.     if (!ap1)
  1140.         return 0;
  1141.     if (isrm(ap1,FALSE)) {
  1142.         if (ap1->length != 6 && ap1->length != 2)
  1143.             return (OCODE *) -2;
  1144.     }
  1145.     else {
  1146.         return (OCODE *)-1;
  1147.     }
  1148.     return make_ocode(ap1,0,0);
  1149. }
  1150. static OCODE *ope_fcom (void)
  1151. {
  1152.     AMODE *ap1;
  1153.     if (lastst != kw_asmreg && lastst != openbr)
  1154.         return make_ocode(0,0,0);
  1155.     ap1 = asm_amode(TRUE);
  1156.     if (!ap1)
  1157.         return 0;
  1158.     if (isrm(ap1,FALSE)) {
  1159.         if (ap1->length != 6 && ap1->length != 8)
  1160.             return (OCODE *) -2;
  1161.     }
  1162.     else {
  1163.         if (ap1->mode != am_freg)
  1164.             return (OCODE *)-1;
  1165.     }
  1166.     return make_ocode(ap1,0,0);
  1167. }
  1168. static OCODE *ope_freg (void)
  1169. {
  1170.     AMODE *ap1;
  1171.     ap1 = asm_amode(TRUE);
  1172.     if (!ap1)
  1173.         return 0;
  1174.     if (ap1->mode != am_freg)
  1175.         return (OCODE *)-1;
  1176.     return make_ocode(ap1,0,0);
  1177. }
  1178. static OCODE *ope_ficom (void)
  1179. {
  1180.     AMODE *ap1,*ap2;
  1181.     ap1 = asm_amode(TRUE);
  1182.     if (!ap1)
  1183.         return 0;
  1184.     if (!isrm(ap1,FALSE))
  1185.         return (OCODE *)-1;
  1186.     if (ap1->length != 2 && ap1->length != 6)
  1187.         return (OCODE *)-2;
  1188.     return make_ocode(ap1,0,0);
  1189. }
  1190. static OCODE *ope_fild (void)
  1191. {
  1192.     AMODE *ap1;
  1193.     ap1 = asm_amode(TRUE);
  1194.     if (!ap1)
  1195.         return 0;
  1196.     if (! isrm(ap1,FALSE))
  1197.         return (OCODE *)-1;
  1198.     if (ap1->length != 2 && ap1->length != 6 && ap1->length != 8)
  1199.         return (OCODE *) -2;
  1200.     return make_ocode(ap1,0,0);
  1201. }
  1202. static OCODE *ope_fist (void)
  1203. {
  1204.     AMODE *ap1;
  1205.     ap1 = asm_amode(TRUE);
  1206.     if (!ap1)
  1207.         return 0;
  1208.     if (! isrm(ap1,FALSE))
  1209.         return (OCODE *)-1;
  1210.     if (ap1->length != 2 && ap1->length != 6)
  1211.         return (OCODE *) -2;
  1212.     return make_ocode(ap1,0,0);
  1213. }
  1214. static OCODE *ope_fld (void)
  1215. {
  1216.     AMODE *ap1;
  1217.     ap1 = asm_amode(TRUE);
  1218.     if (!ap1)
  1219.         return 0;
  1220.     if (isrm(ap1,FALSE)) {
  1221.         if (ap1->length != 6 && ap1->length != 8 && ap1->length != 10)
  1222.             return (OCODE *) -2;
  1223.     }
  1224.     else if (ap1->mode != am_freg)
  1225.         return (OCODE *)-1;
  1226.     return make_ocode(ap1,0,0);
  1227. }
  1228. static OCODE *ope_fst (void)
  1229. {
  1230.     AMODE *ap1;
  1231.     ap1 = asm_amode(TRUE);
  1232.     if (!ap1)
  1233.         return 0;
  1234.     if (isrm(ap1,FALSE)) {
  1235.         if (ap1->length != 6 && ap1->length != 8)
  1236.             return (OCODE *) -2;
  1237.     }
  1238.     else if (ap1->mode != am_freg || ap1->preg == 0)
  1239.         return (OCODE *)-1;
  1240.     return make_ocode(ap1,0,0);
  1241. }
  1242. static OCODE *ope_fstp (void)
  1243. {
  1244.     AMODE *ap1;
  1245.     ap1 = asm_amode(TRUE);
  1246.     if (!ap1)
  1247.         return 0;
  1248.     if (isrm(ap1,FALSE)) {
  1249.         if (ap1->length != 6 && ap1->length != 8 && ap1->length != 10)
  1250.             return (OCODE *) -2;
  1251.     }
  1252.     else if (ap1->mode != am_freg || ap1->preg == 0)
  1253.         return (OCODE *)-1;
  1254.     return make_ocode(ap1,0,0);
  1255. }
  1256. static OCODE *ope_fucom (void)
  1257. {
  1258.     AMODE *ap1;
  1259.     if (lastst != kw_asmreg)
  1260.         return make_ocode(0,0,0);
  1261.      ap1 = asm_amode(TRUE);
  1262.     if (!ap1)
  1263.         return 0;
  1264.     if (ap1->mode != am_freg || ap1->preg == 0)
  1265.         return (OCODE *)-1;
  1266.     return make_ocode(ap1,0,0);
  1267.                                                 
  1268. }
  1269. static OCODE *ope_fxch (void)
  1270. {
  1271.     return ope_fucom();
  1272. }
  1273. static OCODE *ope_mn (void)
  1274. {
  1275.     AMODE *ap1;
  1276.     ap1 = asm_amode(TRUE);
  1277.     if (!ap1)
  1278.         return 0;
  1279.     if (!isrm(ap1,FALSE))
  1280.         return (OCODE *)-1;
  1281.     ap1->length = 10;
  1282.     return make_ocode(ap1,0,0);
  1283. }
  1284. static OCODE *ope_m16 (void)
  1285. {
  1286.     AMODE *ap1;
  1287.     ap1 = asm_amode(TRUE);
  1288.     if (!ap1)
  1289.         return 0;
  1290.     if (!isrm(ap1,TRUE))
  1291.         return (OCODE *)-1;
  1292.     if (ap1->mode == am_dreg)
  1293.         if  (op != op_fstsw && op != op_fnstsw && op != op_fldsw && ap1->preg != 0) 
  1294.             return (OCODE *)-1;
  1295.     if (ap1->length != 2)
  1296.         return (OCODE *) -2;
  1297.     return make_ocode(ap1,0,0);
  1298. }
  1299. static OCODE *ope_cmps(void)
  1300. {
  1301.     AMODE *ap1,*ap2;
  1302.     ap1 = asm_amode(TRUE);
  1303.     if (!ap1)
  1304.         return 0;
  1305.     needpunc(comma,0);
  1306.     ap2 = asm_amode(TRUE);
  1307.     if (!ap2)
  1308.         return 0;
  1309.     if (ap1->mode != am_indisp || ap2->mode != am_indisp)
  1310.         return (OCODE *)-1;
  1311.     if (ap1->preg != 6 || ap2->preg != 7)
  1312.         return (OCODE *)-1;
  1313.     if (ap1->offset || ap2->offset)
  1314.         return (OCODE *)-1;
  1315.     if (!ap1->seg || ap2->seg != 3)
  1316.         return (OCODE *)-1;
  1317.     if (!ap1->length && !ap2->length)
  1318.         return (OCODE *)-2;
  1319.     return make_ocode(ap1,ap2,0);
  1320. }
  1321. static OCODE *ope_ins(void)
  1322. {
  1323.     AMODE *ap1,*ap2;
  1324.         ap1 = asm_amode(TRUE);
  1325.         if (!ap1)
  1326.             return 0;
  1327.         needpunc(comma,0);
  1328.         ap2 = asm_amode(TRUE);
  1329.         if (!ap2)
  1330.             return 0;
  1331.         if (ap1->mode != am_indisp || ap2->mode != am_dreg)
  1332.             return (OCODE *)-1;
  1333.         if (ap1->offset)
  1334.             return (OCODE *)-1;
  1335.         if (ap1->preg != 7 || ap2->preg != 2)
  1336.             return (OCODE *)-1;
  1337.         if (ap2->seg || ap1->seg != 3)
  1338.             return (OCODE *)-1;
  1339.         if (ap2->length != 2 || !ap1->length)
  1340.             return (OCODE *)-2;
  1341.         return make_ocode(ap1,ap2,0);
  1342. }
  1343. static OCODE *ope_lods(void)
  1344. {    
  1345.     AMODE *ap1,*ap2;
  1346.         ap1 = asm_amode(TRUE);
  1347.         if (!ap1)
  1348.             return 0;
  1349.         if (ap1->mode != am_indisp || ap1->offset)
  1350.             return (OCODE *)-1;
  1351.         if (ap1->preg != 6)
  1352.             return (OCODE *)-1;
  1353.         if (!ap1->length)
  1354.             return (OCODE *)-2;
  1355.         return make_ocode(ap1,0,0);
  1356. }
  1357. static OCODE *ope_movs(void)
  1358. {
  1359.     AMODE *ap1,*ap2;
  1360.     ap2 = asm_amode(TRUE);
  1361.     if (!ap2)
  1362.         return 0;
  1363.     needpunc(comma,0);
  1364.     ap1 = asm_amode(TRUE);
  1365.     if (!ap1)
  1366.         return 0;
  1367.     if (ap1->mode != am_indisp || ap2->mode != am_indisp)
  1368.         return (OCODE *)-1;
  1369.     if (ap1->preg != 6 || ap2->preg != 7)
  1370.         return (OCODE *)-1;
  1371.     if (ap1->offset || ap2->offset)
  1372.         return (OCODE *)-1;
  1373.     if (!ap1->seg || ap2->seg != 3)
  1374.         return (OCODE *)-1;
  1375.     if (!ap1->length && !ap2->length)
  1376.         return (OCODE *)-2;
  1377.     return make_ocode(ap2,ap1,0);
  1378. }
  1379. static OCODE *ope_outs(void)
  1380. {
  1381.     AMODE *ap1,*ap2;
  1382.         ap1 = asm_amode(TRUE);
  1383.         if (!ap1)
  1384.             return 0;
  1385.         needpunc(comma,0);
  1386.         ap2 = asm_amode(TRUE);
  1387.         if (!ap2)
  1388.             return 0;
  1389.         if (ap2->mode != am_indisp || ap1->mode != am_dreg || ap2->offset)
  1390.             return (OCODE *)-1;
  1391.         if (ap2->preg != 6 || ap1->preg != 2)
  1392.             return (OCODE *)-1;
  1393.         if (ap1->seg || ap2->seg != 2)
  1394.             return (OCODE *)-1;
  1395.         if (ap1->length != 2 || !ap2->length)
  1396.             return (OCODE *)-2;
  1397.         return make_ocode(ap1,ap2,0);
  1398.     
  1399. }
  1400. static OCODE *ope_scas(void)
  1401. {
  1402.     AMODE *ap1,*ap2;
  1403.         ap1 = asm_amode(TRUE);
  1404.         if (!ap1)
  1405.             return 0;
  1406.         if (ap1->mode != am_indisp || ap1->offset)
  1407.             return (OCODE *)-1;
  1408.         if (ap1->preg != 7)
  1409.             return (OCODE *)-1;
  1410.         if (ap1->seg != 3)
  1411.             return (OCODE *)-1;
  1412.         if (!ap1->length)
  1413.             return (OCODE *)-2;
  1414.         return make_ocode(ap1,0,0);
  1415. }
  1416. static OCODE *ope_xlat(void)
  1417. {
  1418.     AMODE *ap1,*ap2;
  1419.         ap1 = asm_amode(TRUE);
  1420.         if (!ap1)
  1421.             return 0;
  1422.         if (ap1->mode != am_indisp || ap1->offset)
  1423.             return (OCODE *)-1;
  1424.         if (ap1->preg != 3)
  1425.             return (OCODE *)-1;
  1426.         if (ap1->length && ap1->length != 1)
  1427.             return (OCODE *)-2;
  1428.         ap1->length = 1;
  1429.         return make_ocode(ap1,0,0);
  1430. }
  1431. static OCODE *ope_reg32(void)
  1432. {
  1433.     AMODE *ap1 = asm_amode(TRUE);
  1434.     if (!ap1)
  1435.         return 0;
  1436.     if (ap1->mode != am_dreg)
  1437.         return (OCODE *)-1;
  1438.     if (ap1->length != 4)
  1439.         return (OCODE *)-2;
  1440.     return make_ocode(ap1,0,0);
  1441. }
  1442. static OCODE *ope_stos(void)
  1443. {
  1444.     return ope_scas();
  1445. }
  1446. OCODE *(*funcs[])(void) = {
  1447.     0, ope_math,ope_arpl,ope_bound ,ope_bitscan ,ope_bit ,ope_call ,ope_incdec, 
  1448.     ope_rm ,ope_enter ,ope_imul ,ope_in ,ope_imm8 ,ope_relbra ,ope_relbr8, 
  1449.     ope_jmp ,ope_regrm ,ope_loadseg ,ope_lgdt ,ope_lidt ,ope_rm16 ,ope_mov ,
  1450.     ope_movsx ,ope_out ,ope_pushpop ,ope_shift ,ope_ret ,ope_set ,ope_shld ,
  1451.     ope_test ,ope_xchg ,ope_fmath ,ope_fmathp ,ope_fmathi ,ope_fcom ,ope_freg ,
  1452.     ope_ficom ,ope_fild ,ope_fist ,ope_fld ,ope_fst ,ope_fstp ,ope_fucom ,
  1453.     ope_fxch ,ope_mn, ope_m16, ope_cmps, ope_ins, ope_lods, ope_movs,
  1454.     ope_outs, ope_scas, ope_stos, ope_xlat, ope_reg32  };
  1455. SNODE *asm_statement (int shortfin)
  1456. {
  1457.     SNODE *snp=0, **snpp = &snp;
  1458.     OCODE *rv;
  1459.     ENODE *node;
  1460.     ASMNAME *ki;
  1461.     int iserr = 0;
  1462.     lastsym = 0;
  1463.     do {
  1464.         (*snpp) = xalloc(sizeof(SNODE));
  1465.         (*snpp)->stype = st_asm;
  1466.         (*snpp)->label = 0;
  1467.         (*snpp)->exp = 0;
  1468.         (*snpp)->next = 0;
  1469.         if (lastst != kw_asminst) {
  1470.             if (lastst == kw_int) {
  1471.                 getsym();
  1472.                 op = op_int;
  1473.                 rv = ope_imm8();
  1474.                 goto join;
  1475.             }
  1476.             node = asm_label();
  1477.             if (!node)
  1478.                 return (*snpp);
  1479.             asmline = shortfin;
  1480.             if (lastst==semicolon)
  1481.                 getsym();
  1482.             (*snpp)->stype = st_label;
  1483.             (*snpp)->label = (SNODE *)node->v.i;
  1484.             return (*snpp);
  1485.         }
  1486.         ki = keyimage;
  1487.         op = asm_op();
  1488.         if (op == -1)
  1489.             return (*snpp);
  1490.         if (keyimage->amode == 0) {
  1491.             rv = xalloc(sizeof(OCODE));
  1492.             rv->oper1=rv->oper2=rv->oper3 = 0;
  1493.         }
  1494.         else {
  1495.             rv = (*funcs[ki->amode])();
  1496. join:
  1497.             if (!rv || rv == (OCODE *)-1 || rv == (OCODE *)-2) {
  1498.                 if (rv == (OCODE *)-1 )
  1499.                     asm_err(ERR_AILLADDRESS);
  1500.                 if (rv == (OCODE *)-2 )
  1501.                     asm_err(ERR_AINVSIZE);
  1502.                 iserr=1;
  1503.                 return (snp);
  1504.             }
  1505.         }
  1506.         if (rv->oper1 && rv->oper2) {
  1507.             if (!rv->oper1->length)
  1508.                 if (!rv->oper2->length) {
  1509.                     asm_err(ERR_AINVSIZE);
  1510.                     iserr=1;
  1511.                 }
  1512.                 else
  1513.                     rv->oper1->length = rv->oper2->length;
  1514.             else
  1515.                 if (!rv->oper2->length)
  1516.                     rv->oper2->length = rv->oper1->length;
  1517.         }
  1518.         rv->noopt = TRUE;
  1519.         rv->opcode = op;
  1520.         rv->fwd = rv->back = 0;
  1521.         (*snpp)->exp = rv;
  1522.         snpp = &(*snpp)->next;
  1523.     } while (op == op_rep || op == op_repnz || op == op_repz || op == op_repe || op == op_repne || op == op_lock);
  1524.     asmline = shortfin;
  1525.     if (!iserr)
  1526.         needpunc(semicolon,0);
  1527.     else if (lastst == semicolon)
  1528.         getsym();
  1529.     return (snp);
  1530. }